﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.ServiceModel.Activation;
using Ashlen.Portal.Core;
using Ashlen.Portal.Core.DTO;
using Ashlen.Portal.Core.DataInterfaces;
using Ashlen.Portal.Data;
using System.Web;
using System.Web.Security;
using System.Web.Mvc;
using System.Web.Caching;
using Ashlen.Portal.Data.SqlServer;

namespace Ashlen.Portal.Services
{
    // NOTE: If you change the class name "MembershipService" here, you must also update the reference to "MembershipService" in Web.config.
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class MembershipService : ServiceBase, IMembershipService
    {
        private readonly ISecurityDao _securityDao;
        private readonly IUtilityDao _utility;

        public MembershipProvider Provider {
            get;
            private set;
        }

        public MembershipService() {
            Provider = Membership.Provider;
            _securityDao = new SecurityDao();
            _utility = new UtilityDao();

        }

        public string SendPasswordViaEmail(string emailAddress) {
            bool error = false;
            ServiceResponse response = new ServiceResponse();
            try {
                base.SetCache();
                
                string userName = Provider.GetUserNameByEmail(emailAddress);
                if (userName == null || userName == string.Empty) {
                    response.Payload = "* Specified email does not exist.";
                    error = true;
                }
                MembershipUser currentUser = null;
                if (error == false) {
                    currentUser = Provider.GetUser(userName, false);
                    if (currentUser == null) {
                        response.Payload = "* Specified email does not exist.";
                        error = true;
                    }
                }

                if (error == false) {
                    var info = _securityDao.GetPersonalInfo((currentUser != null ? new Guid(currentUser.ProviderUserKey.ToString()) : default(Guid)))
                        as aspnet_UserPersonalInfo;
                    string emailBody = string.Format(@"Dear {1}{0}{0}You requested that your password be emailed to you. {0}{0}
Your user id is: {5}{0}
Your password is: {2}{0}{0}
If you did not initiate this action, then please ignore this email.{0} 
You can login at <a href={4}/Account/Login>{4}</a>{0}{0}
With Regards {0}{3} Support Team",
                                                                  "<br/>", info.Firstname + " " + info.Lastname,
                                                                  currentUser.GetPassword(),
                                                                  UtilityDao.Instance.GetConfig(Constants.APPLICATION, "ApplicationName"),
                                                                  _utility.GetConfig(Constants.APPLICATION, "ApplicationUrl"),
                                                                  currentUser.UserName);

                    _utility.SendEmail(Constants.APPLICATION, true,
                                              _utility.GetConfig(Constants.APPLICATION, "NoReplyEmail"),
                                              emailAddress, string.Empty, string.Empty,
                                              string.Format("{0} Password Retrieval",
                                                            _utility.GetConfig(Constants.APPLICATION, "ApplicationUrl")),
                                              emailBody);
                    response.IsSuccess = true;
                    response.Payload = "Your password has been sent to your email address!";
                }
                else {
                    response.IsSuccess = false;
                }               
            }
            catch (Exception ex) {
                response = Utility.GetErrorResponse(ex);
            }
            return Newtonsoft.Json.JavaScriptConvert.SerializeObject(response);
        }

        public string GetUserDetails(string userGuidAsString)
        {
            ServiceResponse response = new ServiceResponse();
            try {
                base.SetCache();

                Guid userGuid = new Guid(userGuidAsString);                
                MembershipUser user = Provider.GetUser(userGuid, true);
                var info = _securityDao.GetPersonalInfo((user != null ? new Guid(user.ProviderUserKey.ToString()) : default(Guid))) as aspnet_UserPersonalInfo;
                var pref = _securityDao.GetEmailPref((user != null ? new Guid(user.ProviderUserKey.ToString()) : default(Guid))) as aspnet_UserEmailPreference;

                var userObj = new
                {
                    User = new { UserId=userGuid.ToString(), user.UserName, user.IsLockedOut, 
                                 LastActivityDate = user.LastActivityDate.ToString("dd MMM yyyy hh:mm:ss tt"),
                                 Email=user.Email,
                                 LastLockoutDate = user.LastLockoutDate.ToString("dd MMM yyyy"),
                                 CreationDate = user.CreationDate.ToString("dd MMM yyyy hh:mm:ss tt")
                    },
                    Info = new { info.UserId, info.Firstname, info.Lastname, info.Country, info.Nickname, DateCreated = info.DateCreated.ToString("dd MMM yyyy hh:mm:ss tt"),
                                 DateOfBirth = (info.DateOfBirth.HasValue ? info.DateOfBirth.Value.ToString("dd MMM yyyy hh:mm:ss tt") : string.Empty), 
                                 Postcode = (info.Postcode.HasValue ? info.Postcode.Value.ToString() : string.Empty),
                                 info.State,
                                 info.Mobile,
                                 info.Phone,
                                 info.Comment,
                                 info.Avatar,
                                 info.Sex
                    },
                    Pref = new { pref.AcceptAdvertisingEmail, pref.AcceptCommunityEmail }
                };
                response.IsSuccess = true;
                response.Payload = userObj;
            }
            catch (Exception ex)
            {
                response = Utility.GetErrorResponse(ex);
            }
            return Newtonsoft.Json.JavaScriptConvert.SerializeObject(response);
        }

        public string SaveAvatarFromLayout(string userGuid, string layout)
        {
            ServiceResponse response = new ServiceResponse();
            try {
                base.SetCache();

                var userId = new Guid(userGuid);
                layout = layout.Substring(layout.IndexOf("/images", StringComparison.CurrentCultureIgnoreCase), layout.Length - layout.IndexOf("/images", StringComparison.CurrentCultureIgnoreCase));
                layout = System.Web.Hosting.HostingEnvironment.MapPath(layout);
                byte[] avatar = System.IO.File.ReadAllBytes(layout); 
                _securityDao.SaveAvatar(userId, avatar);
                response.IsSuccess = true;
            }
            catch (Exception ex)
            {
                response = Utility.GetErrorResponse(ex);
            }
            return Newtonsoft.Json.JavaScriptConvert.SerializeObject(response);
        }

        /// <summary>
        /// Email Body Parameters:
        /// 0 - new line
        /// 1 - first name
        /// 2 - lastname
        /// 3 - username
        /// 4 - password
        /// 5 - user id
        /// 6 - activation id
        /// 7 - application domain
        /// 8 - application name
        /// </summary>
        /// <param name="firstName"></param>
        /// <param name="lastName"></param>
        /// <param name="username"></param>
        /// <param name="activationGuid"></param>
        /// <returns></returns>
        private string CreateEmail(string firstName, string lastName, string username, string activationGuid, string userId, string password)
        {

            var emailBody = string.Format(_utility.GetFromEmailTemplate("WelcomeEmail"), 
                Environment.NewLine, 
                firstName, 
                lastName,
                username, 
                password,
                userId,
                activationGuid,
                _utility.GetConfig(Constants.APPLICATION, "ApplicationName"),
                _utility.GetConfig(Constants.APPLICATION, "ApplicationName"));
            return emailBody;
        }

        public string RegisterUser(User user)
        {
            ServiceResponse response = new ServiceResponse();
            try
            {
                var errors = new System.Collections.ArrayList();
                base.SetCache();

                var ErrorDetails = new System.Collections.Hashtable();
                ErrorDetails.Add(MembershipCreateStatus.DuplicateEmail, "Duplicate email address was provided.");
                ErrorDetails.Add(MembershipCreateStatus.DuplicateUserName, "Duplicate user name was provided.");
                ErrorDetails.Add(MembershipCreateStatus.InvalidEmail, "Invalid email address was provided.");
                ErrorDetails.Add(MembershipCreateStatus.InvalidPassword, "Invalid password was provided.");
                ErrorDetails.Add(MembershipCreateStatus.InvalidUserName, "Invalid username was provded.");

                string activationGuid = System.Guid.NewGuid().ToString();
                // Attempt to register the user
                MembershipCreateStatus createStatus;
                MembershipUser newUser = Provider.CreateUser(user.basicInfo.Username, user.basicInfo.Password, user.basicInfo.Email,
                    null, null, false, null, out createStatus);
                if (createStatus != MembershipCreateStatus.Success)
                {
                    errors.Add(new { Message = ErrorDetails[createStatus] });
                    response.Payload = errors;
                    response.IsSuccess = false;
                }
                else
                {
                    // Create extra user data 
                    _securityDao.CreatePersonalInfo(new Guid(newUser.ProviderUserKey.ToString()), user.basicInfo.Firstname,
                                                    user.basicInfo.Lastname, user.personalInfo.Nickname,
                                                    user.personalInfo.FormattedDateOfBirth, user.personalInfo.Sex, user.personalInfo.Mobile,
                                                    user.personalInfo.Phone, user.personalInfo.Country, user.personalInfo.State,
                                                    user.personalInfo.FormattedPostcode, activationGuid,
                                                    user.mailSettings.AcceptCommunityEmail, user.mailSettings.AcceptAdvertisingEmail);

                    // send confirmation email                    
                    var emailBody = CreateEmail(user.basicInfo.Firstname, user.basicInfo.Lastname, user.basicInfo.Username, activationGuid,
                        newUser.ProviderUserKey.ToString(), user.basicInfo.Password);
                    _utility.SendEmail(Constants.APPLICATION, true,
                                       _utility.GetConfig(Constants.APPLICATION, "NoReplyEmail"),
                                       user.basicInfo.Email, string.Empty, string.Empty,
                                       string.Format("{0} Account Confirmation",
                                                     _utility.GetConfig(Constants.APPLICATION, "ApplicationUrl")),
                                       emailBody);
                    response.IsSuccess = true;
                }
                #region Validation
                /*
                if (String.IsNullOrEmpty(username))
                {
                    errors.Add("You must specify a username.");
                }
                if (String.IsNullOrEmpty(email))
                {
                    errors.Add("You must specify an email address.");
                }
                if (password == null || password.Length < Provider.MinRequiredPasswordLength)
                {
                    errors.Add(String.Format(CultureInfo.InvariantCulture,
                                             "You must specify a password of {0} or more characters.",
                                             Provider.MinRequiredPasswordLength));
                }
                if (!String.Equals(password, confirmPassword, StringComparison.Ordinal))
                {
                    errors.Add("The password and confirmation do not match.");
                }
                if (String.IsNullOrEmpty(firstName))
                {
                    errors.Add("You must specify a first name.");
                }
                if (String.IsNullOrEmpty(lastName))
                {
                    errors.Add("You must specify a last name.");
                }
                if (String.IsNullOrEmpty(sex))
                {
                    errors.Add("You must specify a gender.");
                }
                if (String.IsNullOrEmpty(country))
                {
                    errors.Add("You must specify a country.");
                }
                if (String.IsNullOrEmpty(state))
                {
                    errors.Add("You must specify a state.");
                }
                */
                #endregion
            }
            catch (Exception ex)
            {
                response = Utility.GetErrorResponse(ex);
            }
            return Newtonsoft.Json.JavaScriptConvert.SerializeObject(response);
        }

        public string SaveUserDetails(User user)
        {
            ServiceResponse response = new ServiceResponse();
            try {
                base.SetCache();

                _securityDao.CreatePersonalInfo(new Guid(user.basicInfo.Id), user.basicInfo.Firstname, user.basicInfo.Lastname,
                    user.personalInfo.Nickname, user.personalInfo.FormattedDateOfBirth, user.personalInfo.Sex, user.personalInfo.Mobile,
                    user.personalInfo.Phone, user.personalInfo.Country, user.personalInfo.State, user.personalInfo.FormattedPostcode,
                    user.personalInfo.Comment, user.mailSettings.AcceptCommunityEmail, user.mailSettings.AcceptAdvertisingEmail);
                response.IsSuccess = true;
            }
            catch (Exception ex)
            {
                response = Utility.GetErrorResponse(ex);
            }
            return Newtonsoft.Json.JavaScriptConvert.SerializeObject(response);
        }
    }
}
